package com.sina.interfaces.core.web.filter;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.sina.interfaces.core.exception.InterfaceCustomException;
import com.sina.interfaces.core.util.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.util.NestedServletException;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


import static com.sina.interfaces.core.util.JsonUtils.OBJECT_MAPPER;

/**
 * 用于在生产环境捕捉 未预期的异常
 * created  on 12/05/2017.
 */
@WebFilter(urlPatterns = "/*",asyncSupported = true,dispatcherTypes =
        {DispatcherType.REQUEST,DispatcherType.FORWARD, DispatcherType.ASYNC,DispatcherType.ERROR})
@Component("globalExceptionFilter")
public class GlobalExceptionFilter extends GenericFilterBean {

    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionFilter.class);




    @Override
    public void doFilter(ServletRequest request, ServletResponse response
            , FilterChain chain) throws IOException, ServletException {
        Map<String, Object> map = new HashMap<>(6);
        try {

            chain.doFilter(request, response);

        }catch (NestedServletException e){
            ResultCode resultCode = null;
            Throwable t = e.getCause();
            if(e.getCause() instanceof InterfaceCustomException){
                 resultCode = ((InterfaceCustomException) e.getCause()).getResultCode();
            }
            if(resultCode == null){
                resultCode = ResultCode.unknown;
            }
            map.put("code", resultCode);
            map.put("msg", t.getMessage() == null ? resultCode : t.getMessage());
            LOG.error("", t);
        } catch (Exception e) {
            map.put("code", ResultCode.unknown);
            map.put("msg", e.getMessage());
            LOG.error("", e);
        }
        if (!map.isEmpty() && !response.isCommitted()) {
            ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            JsonGenerator generator = OBJECT_MAPPER.getFactory().createGenerator(
                    response.getOutputStream(), JsonEncoding.UTF8);
            OBJECT_MAPPER.writeValue(generator, map);
            generator.flush();
        }


    }


}
